﻿/*
 * By David Barrett, Microsoft Ltd. 2012. Use at your own risk.  No warranties are given.
 * 
 * DISCLAIMER:
 * THIS CODE IS SAMPLE CODE. THESE SAMPLES ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
 * MICROSOFT FURTHER DISCLAIMS ALL IMPLIED WARRANTIES INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR OF FITNESS FOR
 * A PARTICULAR PURPOSE. THE ENTIRE RISK ARISING OUT OF THE USE OR PERFORMANCE OF THE SAMPLES REMAINS WITH YOU. IN NO EVENT SHALL
 * MICROSOFT OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
 * BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE THE
 * SAMPLES, EVEN IF MICROSOFT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION
 * OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
 * */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;

namespace SOAP_Test_Application
{
    public partial class FormReplaceTemplateFields : Form
    {
        private string _TemplateXML = "";
        private Form _Owner = null;
        private string[] _distinguishedFolders = {"calendar","contacts","deleteditems","drafts","inbox","journal","notes","outbox","sentitems",
                                                     "tasks","msgfolderroot","publicfoldersroot","root", "junkemail", "searchfolders","voicemail","recoverableitemsroot",
                                                     "recoverableitemsdeletions", "recoverableitemsversions","recoverableitemspurges","archiveroot",
                                                     "archivemsgfolderroot","archivedeleteditems","archiverecoverableitemsroot",
                                                     "archiverecoverableitemsdeletions","archiverecoverableitemsversions",
                                                     "archiverecoverableitemspurges","syncissues","conflicts","localfailures","serverfailures","receipientcache",
                                                     "quickcontacts","conversationhistory","todosearch"};
        public FormReplaceTemplateFields()
        {
            InitializeComponent();
        }

        public string ReplaceTemplateFields(string TemplateXML, Form Owner)
        {
            // Replace any fields in the template as per the user configuration
            _TemplateXML = TemplateXML;
            _Owner = Owner;
            if (!PopulateFieldList()) return TemplateXML;
            textBoxTemplateXML.Text = _TemplateXML;
            this.ShowDialog(Owner);
            ReplaceFields();
            return _TemplateXML;
        }

        private void ReplaceFields()
        {
            // Replace the field placeholders with the values from the datagrid
            for(int i=0;i<dataGridViewFields.Rows.Count; i++)
            {
                DataGridViewRow oRow = dataGridViewFields.Rows[i];
                string sFieldName = oRow.Cells[0].Value.ToString();
                string sFieldValue = "";

                if (!string.IsNullOrEmpty((string)oRow.Tag))
                {
                    switch ((string)oRow.Tag)
                    {
                        case "DistinguishedFolderId":
                            sFieldValue = "<t:DistinguishedFolderId Id=\"" + oRow.Cells[1].Value.ToString() + "\" />";
                            break;

                        case "FolderId":
                            string sFolderId = oRow.Cells[1].Value.ToString();
                            if (_distinguishedFolders.Contains(sFolderId.ToLower()))
                            {
                                // This is a distinguished folder
                                sFieldValue = "<t:DistinguishedFolderId Id=\"" + sFolderId.ToLower() + "\" />";
                            }
                            else
                                sFieldValue = "<t:FolderId Id=\"" + sFolderId + "\" />";
                            break;

                        case "ItemId":
                            sFieldValue = "<t:ItemId Id=\"" + oRow.Cells[1].Value.ToString() + "\" />";
                            break;

                        case "AttachmentId":
                            sFieldValue = "<t:AttachmentId Id=\"" + oRow.Cells[1].Value.ToString() + "\" />";
                            break;

                        default:
                            // If we have a tag set, then this field is a multi-row field so we need to process all the rows
                            sFieldName = (string)oRow.Tag;
                            string sFieldValuePart = "";
                            while ((string)oRow.Tag == sFieldName)
                            {
                                sFieldValuePart = "";
                                try
                                {
                                    sFieldValuePart = oRow.Cells[1].Value.ToString();
                                }
                                catch { }
                                i++;
                                // Check in case we have run out of rows!
                                if (i >= dataGridViewFields.Rows.Count)
                                    break;
                                sFieldValue += sFieldValuePart;
                                oRow = dataGridViewFields.Rows[i];
                            }
                            i--;
                            break;
                    }
                }
                else
                {
                    switch (oRow.Cells[1].ValueType.ToString())
                    {
                        case "System.DateTime":
                            //sFieldValue = String.Format("{0:yyyy-MM-dd}T{0:HH:mm:ss}", oRow.Cells[1].Value);
                            if (!String.IsNullOrEmpty((string)oRow.Cells[1].Tag))
                                sFieldValue = String.Format("{0:" + (string)oRow.Cells[1].Tag + "}", oRow.Cells[1].Value);
                            else
                                sFieldValue = String.Format("{0:yyyy-MM-dd}T{0:HH:mm:ss}", oRow.Cells[1].Value);
                            break;
                        default:
                            sFieldValue = "";
                            try
                            {
                                sFieldValue = oRow.Cells[1].Value.ToString();
                            }
                            catch { }
                            break;
                    }
                }

                // Check for True/False, as EWS requires these in lower case
                if (sFieldValue.ToLower() == "true" || sFieldValue.ToLower() == "false")
                    sFieldValue = sFieldValue.ToLower();

                if ( String.IsNullOrEmpty(sFieldValue))
                {
                    // No value, so check if we have any delete markers (which identify the XML that needs to be removed if this field is blank)
                    if (_TemplateXML.Contains("<!--DELETEMARKERSTART:" + sFieldName + "-->"))
                    {
                        int iDeleteStart = _TemplateXML.IndexOf("<!--DELETEMARKERSTART:" + sFieldName + "-->");
                        string sDeleteEnd = "<!--DELETEMARKEREND:" + sFieldName + "-->";
                        int iDeleteEnd = _TemplateXML.IndexOf(sDeleteEnd);
                        if (iDeleteEnd >= 0)
                        {
                            iDeleteEnd += sDeleteEnd.Length;
                            _TemplateXML = _TemplateXML.Substring(0, iDeleteStart) + _TemplateXML.Substring(iDeleteEnd);
                        }
                    }
                }
                Regex oRegEx = new Regex("<!--FIELD:" + sFieldName + ";.*?-->");
                _TemplateXML = oRegEx.Replace(_TemplateXML, sFieldValue);
            }
        }

        private bool PopulateFieldList()
        {
            Regex oRegEx = new Regex("<!--FIELD:(.*?)-->", RegexOptions.IgnoreCase | RegexOptions.Multiline);
            MatchCollection oMatches = oRegEx.Matches(_TemplateXML);
            if (oMatches.Count == 0) return false;

            foreach (Match oMatch in oMatches)
            {
                AddField(oMatch.Value);
            }
            return true;
        }

        private void AddField(string FieldData)
        {
            // Add the field to the data grid
            
            // "<!--FIELD:Subject;field data-->"
            string sFieldName = FieldData.Substring(10);
            string sFieldValues = "";
            if (!sFieldName.Contains(";"))
                return;

            int iSemiColon = sFieldName.IndexOf(";");
            sFieldValues = sFieldName.Substring(iSemiColon + 1);
            if (sFieldValues.EndsWith("-->"))
                sFieldValues = sFieldValues.Substring(0, sFieldValues.Length - 3);
            sFieldName = sFieldName.Substring(0, iSemiColon);

            string[] sFieldSections = sFieldValues.Split(';');
            string sFieldType = sFieldSections[0];



            DataGridViewRow oRow=new DataGridViewRow();

            DataGridViewTextBoxCell oTextbox = new DataGridViewTextBoxCell();
            oTextbox.Value = sFieldName;
            oRow.Cells.Add(oTextbox);

            switch (sFieldType.ToLower())
            {
                case "string":
                case "folderid":

                case "itemid":
                case "attachmentid":
                    
                    oTextbox = new DataGridViewTextBoxCell();
                    oTextbox.Value="";
                    oRow.Cells.Add(oTextbox);
                    if (sFieldType.ToLower() != "string")
                        oRow.Tag = sFieldType;
                    break;

                case "numeric":
                    oTextbox = new DataGridViewTextBoxCell();
                    oTextbox.Value="";
                    oRow.Cells.Add(oTextbox);
                    break;

                case "date":
                    DataGridViewCalendarCell oDate = new DataGridViewCalendarCell();
                    oDate.Value=DateTime.Now;
                    if (sFieldSections != null)
                    {
                        if (sFieldSections.GetUpperBound(0) > 0)
                        {
                            oDate.Style.Format = sFieldSections[1];
                            oDate.Tag = sFieldSections[1];
                        }
                    }
                    oRow.Cells.Add(oDate);
                    break;

                case "listenerurl":
                    oTextbox = new DataGridViewTextBoxCell();
                    oTextbox.Value = GetListenerUrl();
                    oRow.Cells.Add(oTextbox);
                    break;

                // <!--FIELD:Event Type;ElementCheckedList;t:EventType;CreatedEvent,DeletedEvent,ModifiedEvent,CopiedEvent,MovedEvent-->
                case "elementcheckedlist":
                    string[] sListItems = sFieldSections[2].Split(',');
                    for (int i = 0; i < sListItems.GetUpperBound(0); i++)
                    {
                        oRow = new DataGridViewRow();
                        oRow.Tag = sFieldName;
                        oTextbox = new DataGridViewTextBoxCell();
                        oTextbox.Value = sFieldName + ": " + sListItems[i];
                        oRow.Cells.Add(oTextbox);
                        DataGridViewCheckBoxCell oCheckCell = new DataGridViewCheckBoxCell();
                        oCheckCell.TrueValue = "<" + sFieldSections[1] + ">" + sListItems[i] + "</" + sFieldSections[1] + ">";
                        oRow.Cells.Add(oCheckCell);
                        dataGridViewFields.Rows.Add(oRow);
                    }
                    return;

                case "distinguishedfolderid":
                    // This is a DistinguishedFolderId
                    using (DataGridViewComboBoxCell oComboBox = new DataGridViewComboBoxCell())
                    {
                        foreach (string sValue in _distinguishedFolders)
                            oComboBox.Items.Add(sValue);
                        oComboBox.Value = _distinguishedFolders[0];
                        oRow.Cells.Add(oComboBox);
                    }
                    oRow.Tag = "DistinguishedFolderId";
                    break;


                case "list":
                    // This is a list of values
                    string[] sValues = sFieldSections[1].Split(',');

                    using (DataGridViewComboBoxCell oComboBox = new DataGridViewComboBoxCell())
                    {
                        foreach (string sValue in sValues)
                            oComboBox.Items.Add(sValue);
                        oComboBox.Value = sValues[0];
                        oRow.Cells.Add(oComboBox);
                    }
                    break;

                default:
                    System.Windows.Forms.MessageBox.Show("The field \"" + sFieldType + "\" is not recognised,",
                        "Invalid field", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    break;
            }
            dataGridViewFields.Rows.Add(oRow);
        }

        private void buttonClose_Click(object sender, EventArgs e)
        {
            this.Hide();
        }

        private string GetListenerUrl()
        {
            try
            {
                return (_Owner as FormMain).HTTPListener.URi;
            }
            catch
            {
                return "";
            }
        }

        private void dataGridViewFields_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {

        }
    }



    // CalendarCell


    public class DataGridViewCalendarCell : DataGridViewTextBoxCell
    {
        public DataGridViewCalendarCell()
            : base()
        {
            // Use the short date format.
            this.Style.Format = "dd MMM yyyy hh:mm:ss";
        }

        public DataGridViewCalendarCell(string frm)
            : base()
        {
            // Use the custom format.
            this.Style.Format = frm;
        }

        public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
        {
            // Set the value of the editing control to the current cell value.
            base.InitializeEditingControl(rowIndex, initialFormattedValue,
            dataGridViewCellStyle);
            CalendarEditingControl ctl = DataGridView.EditingControl as CalendarEditingControl;
            ctl.Value = (DateTime)this.Value;
        }

        public override Type EditType
        {
            get
            {
                // Return the type of the editing contol that CalendarCell uses.
                return typeof(CalendarEditingControl);
            }
        }

        public override Type ValueType
        {
            get
            {
                // Return the type of the value that CalendarCell contains.
                return typeof(DateTime);
            }
        }

        public override object DefaultNewRowValue
        {
            get
            {
                // Use the current date and time as the default value.
                return DateTime.Now;
            }
        }
    }

    class CalendarEditingControl : DateTimePicker, IDataGridViewEditingControl
    {
        DataGridView dataGridView;
        private bool valueChanged = false;
        int rowIndex;

        public CalendarEditingControl()
        {
            this.Format = DateTimePickerFormat.Custom;
        }

        // Implements the IDataGridViewEditingControl.EditingControlFormattedValue 
        // property.
        public object EditingControlFormattedValue
        {
            get
            {
                return this.Value.ToString("dd MMM yyyy hh:mm:ss");// (this.CustomFormat);
            }
            set
            {
                String newValue = value as String;
                if (newValue != null)
                {
                    this.Value = DateTime.Parse(newValue);
                }
            }
        }

        // Implements the 
        // IDataGridViewEditingControl.GetEditingControlFormattedValue method.

        public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
        {
            return EditingControlFormattedValue;
        }

        // Implements the 
        // IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.

        public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
        {
            this.Font = dataGridViewCellStyle.Font;
            this.CalendarForeColor = dataGridViewCellStyle.ForeColor;
            this.CalendarMonthBackground = dataGridViewCellStyle.BackColor;
        }

        // Implements the IDataGridViewEditingControl.EditingControlRowIndex 
        // property.

        public int EditingControlRowIndex
        {
            get
            {
                return rowIndex;
            }
            set
            {
                rowIndex = value;
            }

        }

        // Implements the IDataGridViewEditingControl.EditingControlWantsInputKey 
        // method.

        public bool EditingControlWantsInputKey(Keys key, bool dataGridViewWantsInputKey)
        {
            // Let the DateTimePicker handle the keys listed.
            switch (key & Keys.KeyCode)
            {
                case Keys.Left:
                case Keys.Up:
                case Keys.Down:
                case Keys.Right:
                case Keys.Home:
                case Keys.End:
                case Keys.PageDown:
                case Keys.PageUp:
                case Keys.Tab:
                    return true;

                default:
                    return false;
            }
        }

        // Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit 
        // method.
        public void PrepareEditingControlForEdit(bool selectAll)
        {
            // No preparation needs to be done.
        }

        // Implements the IDataGridViewEditingControl
        // .RepositionEditingControlOnValueChange property.
        public bool RepositionEditingControlOnValueChange
        {
            get
            {
                return false;
            }
        }

        // Implements the IDataGridViewEditingControl
        // .EditingControlDataGridView property.
        public DataGridView EditingControlDataGridView
        {
            get
            {
                return dataGridView;
            }
            set
            {
                dataGridView =value;
            }
        }

        // Implements the IDataGridViewEditingControl
        // .EditingControlValueChanged property.
        public bool EditingControlValueChanged
        {
            get
            {
                return valueChanged;
            }
            set
            {
                valueChanged = value;
            }
        }

        // Implements the IDataGridViewEditingControl
        // .EditingPanelCursor property.
        public Cursor EditingPanelCursor
        {
            get
            {
                return base.Cursor;
            }
        }

        protected override void OnValueChanged(EventArgs eventargs)
        {
            // Notify the DataGridView that the contents of the cell
            // have changed.
            valueChanged =true;
            this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
            base.OnValueChanged(eventargs);
        }
    }
}
